package com.lg.jvm.stringtable;

/**
 * 字符串常量池 与运行时常量池 探究
 *
 * @author Gang.Li
 * @date 2021/6/9 16:54
 */
public class StringTableTest {
    public static void main(String[] args) {
        //test1();
        //test2();
        //test3();
        test4();
    }

    private static void test3() {
        String s1 = new String("xiaogang"); // 返回的是 堆的引用
        String s2 = s1.intern();
        String s3 = "xiaogang"; // 返回的是 字符串池的 引用

        System.out.println(s1 == s2);  //false
        System.out.println(s2 == s3); // true
        System.out.println(s2 == s1); // true
    }

    public static void test1() {
        String s1 = "a";
        String s2 = "b";
        String s3 = "a" + "b";
        String s4 = s1 + s2;
        String s5 = "ab";
        String s6 = s4.intern();
        // 问
        System.out.println(s3 == s4);
        System.out.println(s3 == s5);
        System.out.println(s3 == s6);
        String x2 = new String("c") + new String("d");
        String x1 = "cd";
        String intern = x2.intern();

        // 问，如果调换了【最后两行代码】的位置呢，如果是jdk1.6呢
        System.out.println(x1 == x2);
        System.out.println(x2 == intern); // 如果转换位置，在jdk6中 这两个判断都是false，但是在1.7及以上都为true，原因就是在jdk1.6放入串池中的对象是重新复制出来的一个新的对象
        // 在1.7及以上 则为true

    }

    public static void test2() {
        String s1 = "xiaogang";
        String s2 = new String("xiaogang");

        System.out.println(s2 == s1);
        // JDK8 false
        // JDK7 false
        // JDK6 false
    }

    public static void test4() {
        String s1 = "xiaogang";
        String s2 = "1";
        String s3 = "2";
        String s4 = s1 + s2 + s3; // JVM判断该对象也是引用对象，并不是字面量，所以在加载的时候，确定不下来。之后在解析的时候才能知道s4的值，底层是是用的StringBuilder来实现的。
        /*
            为什么底层要使用StringBuild 来实现啊？
                个人理解：在确定s4 的值之后，肯定是不可能放入常量池的，因为已经过了加载的阶段了，那么计算出来的值，需要一个载体去保存，
                所以只有创建一个新的字符串对象去保存该值，并且返回直接引用。
         */
        String s5 = "xiaogang" + "1" + "2";

        System.out.println(s4 == s5); // false
        // JDK8 false
        // JDK7 false
        // JDK6 false
    }

    private static void test5() {
        String a = "ab";
        final String bb = "b";
        String b = "a" + bb;

        System.out.println(a == b); // true
    }

    private static void test6() {
        String a = "ab";
        final String bb = getBB();
        String b = "a" + bb;

        System.out.println(a == b); // false
    }

    private static String getBB() {
        return "b";
    }

}
